package com.zang.blogz.quartz;
import cn.hutool.extra.spring.SpringUtil;
import com.zang.blogz.constant.ScheduleConstant;
import com.zang.blogz.entity.Job;
import com.zang.blogz.entity.JobLog;
import com.zang.blogz.service.JobLogService;
import io.github.vampireachao.stream.core.optional.Opp;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.json.JSONParserConstants;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;



/**
 * @Author: ZVerify
 * @Description: TODO 抽象quartz调用
 * @DateTime: 2022/9/4 9:37
 **/
public abstract class AbstractQuartzJob implements org.quartz.Job {

    private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);


    private static final ThreadLocal<Date> THREAD_LOCAL = new ThreadLocal<>();


    @Override
    public void execute(JobExecutionContext jobExecutionContext) {

        Job job = new Job();

        BeanUtils.copyProperties(jobExecutionContext.getMergedJobDataMap().get(ScheduleConstant.TASK_PROPERTIES),job);

        Opp<Object> quartzOpp = Opp.ofTry(() -> {

            before(jobExecutionContext, job);
            doExecute(jobExecutionContext, job);
            after(jobExecutionContext, job, null);
            return null;
        });

        Opp<Exception> of = Opp.of(quartzOpp.getException());
        if (of.isPresent()){

            log.error("任务执行异常  - ：", of.get());
            after(jobExecutionContext, job , of.get());
        }


    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param job     系统计划任务
     */
    protected void before(JobExecutionContext context, Job job) {
        THREAD_LOCAL.set(new Date());
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param job     系统计划任务
     */
    protected void after(JobExecutionContext context, Job job, Exception e) {
        Date startTime = THREAD_LOCAL.get();
        THREAD_LOCAL.remove();
        final JobLog jobLog = new JobLog();
        jobLog.setJobId(job.getId());
        jobLog.setJobName(job.getJobName());
        jobLog.setJobGroup(job.getJobGroup());
        jobLog.setInvokeTarget(job.getInvokeTarget());
        jobLog.setStartTime(startTime);
        jobLog.setEndTime(new Date());
        long runMs = jobLog.getEndTime().getTime() - jobLog.getStartTime().getTime();
        jobLog.setJobMessage(jobLog.getJobName() + " 总共耗时：" + runMs + "毫秒");
        if (e != null) {
            jobLog.setStatus(JSONParserConstants.EOF);
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw, true));
            String str = sw.toString();
            String errorMsg = StringUtils.substring(str, 0, 2000);
            jobLog.setExceptionInfo(errorMsg);
        } else {
            jobLog.setStatus(JSONParserConstants.C_SINGLE_COMMENT);
        }
        // 写入数据库当中
        SpringUtil.getBean(JobLogService.class).save(jobLog);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param job     系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, Job job) throws Exception;
}
